import { Engine } from "../engine";
import { DateUtil } from '../../utils/dateUtil';
import { CommonOrderStatus, OrderSortType, DocType } from "../common/docDefinition";
import { WareHouse } from "./warehouse";
import { SubCommodity } from "../commodity/subCommodity";
import { CsDouble } from "../common/csDouble";
import { MeasurementUnit } from "../basicData/measurementUnit";
import { DocBase } from "../common/docBase";
import { OrderUtil } from "../../utils/orderUtil";
import { Util } from "../../utils/util";

/// 过滤条件
export class InventorySheetFilter {
    /// 单号
    inventoryId = null;

    /// 单据标题
    inventoryTitle = null;

    /// CommonOrderStatus 状态 0 all, 1 未审核，2 已审核  for desktop and web
    /// 类型 CommonOrderStatus 中的code
    status = null;

    /// 仓库 WareHouse
    warehouse = null;

    /// 规格商品名称
    subCommodityName = null;

    /// 开始时间
    startDate = null;

    /// 结束时间
    endDate = null;

    /// 排序方式, 默认按创建时间排序
    sortType = OrderSortType.CreateTime.code;

    /// 门店过滤
    storeId = null;

    constructor(storeId = null) {
        this.storeId = storeId || Engine.profile?.filterStore?.id;
    }

    clear() {
        this.inventoryId = null;
        this.inventoryTitle = null;
        this.warehouse = null;
        this.subCommodityName = null;
        this.startDate = null;
        this.endDate = null;
        this.status = null;
    }

    static clone(filter) {
        const cloned = new InventorySheetFilter();
        cloned.inventoryId = filter.inventoryId;
        cloned.inventoryTitle = filter.inventoryTitle;
        cloned.warehouse = filter.warehouse;
        cloned.subCommodityName = filter.subCommodityName;
        cloned.startDate = filter.startDate;
        cloned.endDate = filter.endDate;
        cloned.status = filter.status;
        cloned.sortType = filter.sortType;
        cloned.storeId = filter.storeId;
        return cloned;
    }

    /// 将过滤条件转换为 JSON 格式
    _$InventorySheetFilterToJson(instance, withState = false) {
        const ret = {};

        if (this.inventoryId && this.inventoryId.length > 0) {
            ret["a_lke_id"] = this.inventoryId;
        }

        if (this.status != null && this.status === CommonOrderStatus.WaitReview.code && withState) {
            ret['a_orderStatus'] = 0;
        }
        if (this.status != null && this.status === CommonOrderStatus.Passed.code && withState) {
            ret['a_orderStatus'] = 1;
        }
        if (this.inventoryTitle && this.inventoryTitle.length > 0) {
            ret["a_lke_orderTitle"] = this.inventoryTitle;
        }
        if (this.warehouse) ret["ign_storageId"] = this.warehouse.id;

        if (this.subCommodityName && this.subCommodityName.length > 0) {
            ret["ign_specName"] = this.subCommodityName;
        }

        if (this.startDate && this.endDate && this.endDate > this.startDate) {
            ret["a_gte_businessTime"] = DateUtil.formatDate(this.startDate, "yyyy-MM-dd HH:mm:ss");
            ret["a_lte_businessTime"] = DateUtil.formatDate(this.endDate, "yyyy-MM-dd HH:mm:ss");
        } else if (this.startDate && !this.endDate) {
            ret["a_gte_businessTime"] = DateUtil.formatDate(this.startDate, "yyyy-MM-dd HH:mm:ss");
        } else if (this.endDate && !this.startDate) {
            ret["a_lte_businessTime"] = DateUtil.formatDate(this.endDate, "yyyy-MM-dd HH:mm:ss");
        }

        if (this.sortType === OrderSortType.CreateTime.code) {
            ret["sort"] = "a.create_time desc";
        } else if (this.sortType === OrderSortType.OperationTime.code) {
            ret["sort"] = "a.business_time desc, a.create_time desc";
        }
        else {
            ret["sort"] = "a.create_time desc";
        }

        // 门店过滤
        if (this.storeId) {
            ret["storeId"] = this.storeId;
        }

        console.log('Inventory Sheet Filter:', ret);

        return ret;
    }

    toJson(withState = false) {
        return this._$InventorySheetFilterToJson(this, withState);
    }
}

/// 盘点商品单品信息
export class CommodityBatchSheet {
    id = "";
    commodity = null;  // SubCommodity
    count = new CsDouble(0);
    _adjustCount = null;   // CsDouble 盘点库存 未设置时为空
    storeId = null;
    selected = false;

    /**
     * 盈亏
     */
    get adjustBalance() {
        return this._adjustCount == null ? CsDouble.zero() : this._adjustCount.sub(this.count);
    }

    /**
     * subCount CsDouble
     */
    addAdjustCount(subCount) {
        if (subCount.toDouble() > 0) {
            this._adjustCount = this._adjustCount == null ? subCount : this._adjustCount.add(subCount);
        }

        return this._adjustCount;
    }

    setCount(count){
        this.count = count;
    }

    // CsDouble   
    setAdjustCount(count) {
        console.log("setAdjustCount", count);
        if (count.toDouble() >= 0) {
            console.log("setAdjustCount 1");
            this._adjustCount = count;
        }
        console.log("_adjustCount after setAdjustCount", this._adjustCount);

        console.log("CommodityBatchSheet after setAdjustCount", this);
    }

    get adjustCount() {
        return this._adjustCount || new CsDouble(0);
    }

    constructor({
        commodity = SubCommodity.empty(),
        count = CsDouble.zero(),
        adjustCount = null,
        id = "",
        storeId = null } = {}) {
        this.commodity = commodity; // SubCommodity
        this.count = count;   /// 当前库存 CsDouble
        this._adjustCount = adjustCount;   /// 盘点库存 未设置时为空 CsDouble
        this.id = id;
        this.storeId = storeId;
        this.selected = false;   /// for ui

        // 检测 commdodity 是否有效
        if (!this.commodity ) {
            throw new Error("CommodityBatchSheet: commodity is required and must be an instance of SubCommodity.");
        }

        // 检测 count 是否有效
        if (!this.count ) {
            throw new Error("CommodityBatchSheet: count is required and must be an instance of CsDouble.");
        }
    }
    //batch  CommodityBatch
    static fromCommodityBatch(batch) {
        return new CommodityBatchSheet({
            commodity: batch.commodity,
            count: batch.inventoryCount,
            adjustCount: batch.count,
            id: batch.id
        });
    }

    static clone(batch) {
        return new CommodityBatchSheet({
            id: batch.id,
            count: batch.count,
            adjustCount: batch.adjustCount,
            commodity: SubCommodity.clone(batch.commodity)
        });
    }

    static fromJson(json) {

        return new CommodityBatchSheet({
            id: Util.jsonToString(json['id']),
            count: Util.jsonToCsDouble(json["preCount"], 0),
            adjustCount: Util.jsonToCsDouble(json["changeCount"], 0),
            commodity: new SubCommodity({
                name: Util.jsonToString(json['commodityName']),
                standard: Util.jsonToString(json['specName']),
                id: Util.jsonToString(json['specId']),
                commodityId: Util.jsonToString(json['commodityId']),
                unit: new MeasurementUnit({
                    id: Util.jsonToString(json['unitId']),
                    name: Util.jsonToString(json['unitName']),
                    supportDecimal: Util.jsonToBool(json['decimalSupport'], false)
                }),
                purchasePrice: Util.jsonToDouble(json['lineCostPrice'], 0),
                retailPrice: Util.jsonToDouble(json['lineRetailPrice'], 0),
                wholesalePrice: Util.jsonToDouble(json['lineTradePrice'], 0),
                imgs: Util.jsonToString(json['specImgs'])
            })
        });
    }

    // for print detail info
    _$CommodityBatchSheetToPrintJson(instance) {
        const ret = {};
        ret['id'] = instance.id;
        ret['count'] = instance.count;
        ret["adjustCount"] = instance.adjustCount;
        ret['commodityName'] = instance.commodity.name;
        ret['commodityId'] = instance.commodity.id;
        return ret;
    }

    toPrintJson() {
        return this._$CommodityBatchSheetToPrintJson(this);
    }
}

/// 盘点单
export class InventorySheet extends DocBase {
    constructor({
        warehouse, // required
        commodityBatch = [],
        // super param
        id, // required
        storeId, // required
        storeName, // required
        remark = "",
        operator = "",
        operatorId = "",
        docMaker = "",
        status = CommonOrderStatus.WaitReview,
        title = "",
        docCode = "",
        parentDocType = null,
        parentDocCode = "",
        parentDocTitle = "",
        sourceDocType = null,
        sourceDocCode = "",
        sourceDocTitle = "",
        recordDateTime = null,
        fromEmtyConstructor = false, // 是否通过empty 构造
    }) {
        if (!warehouse) {
            throw new Error("InventorySheet: warehouse is required.");
        }
        if (!id && !fromEmtyConstructor) {
            throw new Error("InventorySheet: id is required.");
        }
        if (!storeId && !fromEmtyConstructor) {
            throw new Error("InventorySheet: storeId is required.");
        }
        if (!storeName && !fromEmtyConstructor) {
            throw new Error("InventorySheet: storeName is required.");
        }

        super({
            id: id,
            storeId: storeId,
            storeName: storeName,
            title: title,
            docCode: docCode,
            status: status,
            docType: DocType.PDD,
            parentDocType: parentDocType,
            parentDocCode: parentDocCode,
            parentDocTitle: parentDocTitle,
            sourceDocCode: sourceDocCode,
            sourceDocType: sourceDocType,
            sourceDocTitle: sourceDocTitle,
            recordDateTime: recordDateTime,
            operator: operator,
            operatorId: operatorId,
            docMaker: docMaker,
            remark: remark
        });

        this._commodityList = commodityBatch;  //List<CommodityBatchSheet>
        this.warehouse = warehouse;            // WareHouse


    }

    static empty({
        operator = "",
        operatorId = "",
        storeId = "",
        storeName = ""
    } = {}) {
        let inventorySheet = new InventorySheet({
            warehouse: WareHouse.empty(),
            operator: operator,
            operatorId: operatorId,
            storeId: storeId,
            storeName: storeName,
            fromEmtyConstructor: true
        });

        inventorySheet.warehouse = OrderUtil.getOrderDefaultWarehouse(storeId, inventorySheet.warehouse);

        return inventorySheet;

    }

    static clone(data) {
        let warehouse = WareHouse.clone(data.warehouse);
        let commodityList = data.commodityList.map(e => CommodityBatchSheet.clone(e));
        let cloned = new InventorySheet({
            warehouse: warehouse,
            commodityBatch: commodityList,
            id: data.id,
            storeId: data.storeId,
            storeName: data.storeName,
        })
        cloned.docBaseClone(data);
        return cloned;
    }

    // 复制    
    resetForCopy({ removeParentAndSourceData = true }) {
        super.resetForCopy({ removeParentAndSourceData: removeParentAndSourceData });

        // 清除商品列表id
        this._commodityList.forEach(element => {
            element.id = "";
        });
        // 更新库存数量
        // todo 通过商品合集查询商品库存，刷新库存和盘点盈亏
    }

    /// 更新商品列表 List<CommodityBatch>
    updateCommodityFromCommodityBatchList(list) {
        this._commodityList.clear();
        this._commodityList.addAll(list.map(e => new CommodityBatchSheet(e)));
    }

    /// 商品列表
    get commodityList() {
         return [...this._commodityList];
    }

    /// 插入 batch CommodityBatchSheet
    addCommodityBatch(batch) {
        // 不能重复添加
        if (!this._commodityList.some(element => element.commodity.id === batch.commodity.id)) {
            this._commodityList.push(batch);
        }
    }

    /// 插入 batch 或是更新数量 CommodityBatchSheet
    /// 没有该商品，添加，如果有则增加数量
    addOrUpdateCommodityBatch(batch) {
        const existCommodityList = this._commodityList.filter(element => element.commodity.id === batch.commodity.id);
        if (existCommodityList.length === 0) {
            this._commodityList.push(batch);
        } else {
            existCommodityList[0].addAdjustCount(new CsDouble(1));
        }
    }

    /// 删除batch CommodityBatchSheet
    removeCommodityBatch(batch) {
        const index = this._commodityList.indexOf(batch);
        if (index !== -1) {
            this._commodityList.splice(index, 1);
            return true;
        }
        return false;
    }

    /// 清除商品列表
    clearCommodity() {
        this._commodityList.clear();
    }

    /// index CommodityBatchSheet
    indexOfCommodityBatch(batch) {
        return this._commodityList.indexOf(batch);
    }

    /// 检测是否有效
    validateOrder() {

        if(!this.commodityList || this.commodityList.length === 0)
        {
            return "请添加盘点商品";
        }

        for (const item of this.commodityList) {
            if (item.adjustCount == null) {
                return `[${item.commodity.name}] 未设置盘点数量`;
            }
        }
        return null;
    }

    /// 盘盈数量
    getPositiveAdjustCount() {
        return this._commodityList.reduce((acc, item) => acc + (item.adjustBalance.value > 0 ? item.adjustBalance.value : 0), 0);
    }
    /// 盘亏数量
    getNegativeAdjustCount() {
        return this._commodityList.reduce((acc, item) => acc + (item.adjustBalance.value < 0 ? item.adjustBalance.value : 0), 0);
    }

    /**
 * Creates an InventorySheet instance from JSON data
 * @param {Object} json - The JSON data to parse
 */
    static fromJson(json) {
        let baseOrder = DocBase.fromJson(json, DocType.PDD);
        const instance = new InventorySheet({
            warehouse: new WareHouse({
                id: json.storageId || "",
                name: json.storageName || ""
            }),
            fromEmtyConstructor: true
        });

        Object.assign(instance, baseOrder);

        const batchInRecords = json.details || [];
        for (const element of batchInRecords) {
            const batch = CommodityBatchSheet.fromJson(element);
            instance._commodityList.push(batch);

            // 解析仓库信息，后台是1对多，仓库信息在商品中
            if (instance.warehouse.id === "" &&
                element.storageId != null &&
                element.storageName != null) {
                instance.warehouse = new WareHouse({
                    id: element.storageId || "",
                    name: element.storageName || ""
                });
            }
        }

        return instance;
    }

    _$InventorySheetToJson(instance) {
        const ret = super.toJson();
        ret.details = [];

        for (const element of instance._commodityList) {
            const item = {};
            item.changeCount = element.adjustCount ? element.adjustCount.value : 0;
            item.commodityId = element.commodity.commodityId;
            item.id = element.id;
            item.orderId = instance.id;
            item.preCount = element.count.value;
            item.specId = element.commodity.id;
            item.storageId = instance.warehouse.id;
            /// 目前仅直接设定时使用
            item.storeId = element.storeId;
            ret.details.push(item);
        }

        return ret;
    }

    toJson() {
        return this._$InventorySheetToJson(this);
    }

    _$InventorySheetToPrintJson(instance) {
        const ret = {};
        ret.details = [];

        for (const element of instance._commodityList) {
            const item = {};
            item.changeCount = element.adjustCount ? element.adjustCount.value : 0;
            item.commodityId = element.commodity.commodityId;
            item.commodityName = element.commodity.name;
            item.id = element.id;
            item.orderId = instance.id;
            item.preCount = element.count.value;
            item.specId = element.commodity.id;
            item.storageId = instance.warehouse.id;
            item.storageName = instance.warehouse.name;
            ret.details.push(item);
        }

        ret.id = instance.id;
        ret.orderStatus = instance.status.code;
        ret.orderTitle = instance.title;
        ret.orderType = instance.docType.code;
        ret.orgId = Engine.profile.org.orgId;
        ret.businessTime = instance.operateDate.toString();
        ret.updateUser = Engine.profile.nickName;
        ret.remark = instance.remark;
        ret.handleUserName = instance.operator;
        ret.handleUserId = instance.operatorId;

        return ret;
    }

    toPrintInfoJson() {
        return this._$InventorySheetToPrintJson(this);
    }
}
